﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace TurtleLib.ComputerCraft
{
  public partial class OperatingSystem
  {
    private Action<string> _statusUpdateCallback;

    protected Action _bootScript;
    protected DateTime _bootTime;
    protected uint _id;
    protected string _label;

    private static uint s_id;

    static OperatingSystem()
    {
      s_id = 0;
    }

    internal OperatingSystem()
    {
      _statusUpdateCallback = m => { };
      _id = ++s_id;
    }

    protected virtual void Boot()
    {
      _bootTime = System.DateTime.Now;

      if (_bootScript != null)
      {
        _bootScript();
      }

      _statusUpdateCallback("idle");
    }

    /// <summary>
    /// Returns the version of the OS the computer is running
    /// </summary>
    /// <returns>version</returns>
    public string version()
    {
      return "TProt v .1";
    }

    /// <summary>
    /// Returns the unique ID of this computer, os.computerID() also behaves exactly the same as os.getComputerID()
    /// </summary>
    /// <returns>unique id</returns>
    public uint getComputerID()
    {
      return _id;
    }

    /// <summary>
    /// Deprecated. please use getComputerID()
    /// </summary>
    /// <returns></returns>
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public uint computerID() { return getComputerID(); }

    /// <summary>
    /// Returns the label of this computer. os.computerLabel() also behaves exactly the same as os.getCOmuterLabel()
    /// </summary>
    /// <returns>computer label</returns>
    public string getComputerLabel()
    {
      return _label;
    }

    /// <summary>
    /// Deprecated. please use getComputerLabel()
    /// </summary>
    /// <returns></returns>
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public string computerLabel() { return getComputerLabel(); }

    /// <summary>
    /// Sets the label of this computer
    /// </summary>
    /// <param name="label">computer label</param>
    public void setComputerLabel(string label)
    {
      _label = label;
    }

    /// <summary>
    /// not supported
    /// </summary>
    /// <param name="environment"></param>
    /// <param name="programPath"></param>
    /// <param name="arguments"></param>
    public void run(object[] environment, string programPath, params string[] arguments)
    {
      throw new NotSupportedException();
    }

    /// <summary>
    /// not supported
    /// </summary>
    /// <param name="name"></param>
    public void loadAPI(string name)
    {
      throw new NotSupportedException();
    }

    /// <summary>
    /// not supported
    /// </summary>
    /// <param name="name"></param>
    public void unloadAPI(string name)
    {
      throw new NotSupportedException();
    }

    /// <summary>
    /// Blocks until the computer receives an event, or if target-event is
    /// specified, will block until an instance of target-event occurs.
    /// os.pullEvent( target-event ) returns the event and any parameters the
    /// event may have. If a target-event is specified, the computer will not
    /// break for any other events (except termination).
    /// </summary>
    /// <param name="targetEvent"></param>
    public object[] pullEvent(string targetEvent = null)
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Advanced version of pullEvent(). os.pullEventRaw() will block until an
    /// event occurs, and then returns the event (and any parameters the event
    /// may have). Unlike os.pullEvent( target-event ), this function will not
    /// break for system events, and can be used to handle termination events.
    /// </summary>
    /// <returns></returns>
    public object[] pullEventRaw()
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Adds an event to the event queue
    /// </summary>
    /// <param name="targetEvent">name of event</param>
    /// <param name="parameters">parameters for the event</param>
    public void queueEvent(string targetEvent, params object[] parameters)
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// returns the time in seconds(float) since boot
    /// </summary>
    /// <returns>cpu time in seconds</returns>
    public float clock()
    {
      return (float)(DateTime.Now - _bootTime).TotalSeconds;
    }

    /// <summary>
    /// Creates a trigger to queue an event after a number of seconds.
    /// The ID of the timer is returned from this function to differentiate
    /// multiple timers. Timers are one-shot; once they have fired an event you
    /// will need to start another one if you need a recurring timer.
    /// </summary>
    /// <param name="timeout">delay in seconds to queue the event</param>
    public int startTimer(int timeout)
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// makes the system wait a number of seconds
    /// </summary>
    /// <param name="timeout">sleep time in seconds</param>
    public void sleep(int timeout)
    {
      _statusUpdateCallback("Sleeping");
      System.Threading.Thread.Sleep(1000 * timeout);
      _statusUpdateCallback(string.Empty);
    }

    /// <summary>
    /// returns the current minecraft world time
    /// </summary>
    /// <returns>minecraft world time in hours</returns>
    public float time()
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Returns the current minecraft day
    /// </summary>
    /// <returns>minecraft days since spawn generation</returns>
    public int day()
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Creates a trigger to queue an event at an absolute day time
    /// The event name is "alarm"
    /// The event's parameter is its ID
    /// </summary>
    /// <param name="time">day time in hours</param>
    public void setAlarm(float time)
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Turn off the computer
    /// </summary>
    public void shutdown()
    {
      throw new NotImplementedException();
    }

    /// <summary>
    /// Reboot the computer
    /// </summary>
    public void reboot()
    {
      throw new NotImplementedException();
    }
  }
}
